/* Copyright (c) 2010 Fabian Kulman
* 
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
* 
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
* 
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/

#ifndef UNIT
#define UNIT

#include <GL/glut.h>
#include <chipmunk/chipmunk.h>

#define GRABABLE_MASK_BIT (1<<31)	// cpLayers 1-31 
#define NOT_GRABABLE_MASK (~GRABABLE_MASK_BIT) 

static double SCALE = 50.0;
static cpFloat UNIT_MASS = 1.0;
static cpFloat UNIT_MOMENTUM = 10.0;


// Unit vertices
static const int num = 4;
static cpVect verts[] = {
	cpv( -0.498*SCALE, 0 ),
	cpv( 0, 0.288*SCALE ),
	cpv( 0.495*SCALE,0 ),
	cpv( 0, -0.865*SCALE )
};


class Unit{

public:
	cpSpace* space;

	cpBody* body;
	cpShape* shape;
	cpPivotJoint* joint;
	cpRotaryLimitJoint* constraint;

	// Used for looking the position  
	cpBody* staticBody;
	cpShape* staticShape;
	cpPivotJoint* staticJoint;

	cpHashValue id;
	cpFloat localAngle;
	double state;		

	Unit* lu; // Left unit
	Unit* ru; // Right unit

	Unit( cpSpace* space, cpVect pos );
	Unit( cpSpace* space, Unit* lu, cpFloat angle );
	~Unit();

	// Sets all forces and velocities to zero
	void stopUnit();

	// Constraints any movment 
	void lookPosition();
	void unlookPosition();

	// Constraints joint rotations
	void lookJoint();
	void unlookJoint();
	
	// Helps folding near valid states. Example: if angle > 1.8  -> joint is rotated to 2.0943 
	bool snap();

	void updateLocalAngle();
	
	void drawUnit( GLfloat guiScale );

	// Derives the folding state in the [0,1] range 
	static cpFloat Unit::angleToState( cpFloat a ){
		cpFloat state = (a+1.046f)/(2.094f+1.046f);
		if( state > 1.0 ){
			state = 1.0;
		}
		else if( state < 0.0 ){
			state = 0.0;
		}
		return state;
	}
};


#endif